package com.alibaba.csp.sentinel.dashboard.repository.metric;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.util.StringUtils;
import com.alibaba.csp.sentinel.util.StringUtil;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

@Component
@Mapper
public interface MetricEntityMapper {

    @InsertProvider(type = Provider.class,method = "save")
    public void save(@Param("metric") MetricEntity metric);

    @InsertProvider(type = Provider.class,method = "batchSave")

    public void saveAll(List<MetricEntity> list) ;

    @SelectProvider(type = Provider.class, method = "queryList")
    public List<MetricEntity> queryList(@Param("app")String app, @Param("resource")String resource, @Param("startTime")long startTime, @Param("endTime")long endTime);



    class Provider{
        //新增
        public String save(MetricEntity metric) throws IllegalAccessException {
            SQL sql = new SQL(){{
                INSERT_INTO("sentinel_metric");
                Field[] fields = metric.getClass().getDeclaredFields();
                for(int i=0;i<fields.length;i++){
                    String cName = fields[i].getName();
                    if(fields[i].get(metric) != null){
                        VALUES(cName,"#{" + cName + "}");
                    }
                }
            }};
            return sql.toString();
        }
        //批量新增
        public String batchSave(Map param){
            List<MetricEntity> list = (List<MetricEntity>) param.get("list");
            StringBuilder sb = new StringBuilder();
            StringBuilder keyFields = new StringBuilder();
            StringBuilder valueFields = new StringBuilder();
            if(list != null && list.size() > 0){//解析实体类属性
                MetricEntity metric = list.get(0);
                Field[] fields = metric.getClass().getDeclaredFields();
                for(int i=0;i<fields.length;i++){
                    keyFields.append(StringUtils.formatJavaFieldToDb(fields[i].getName()));
                    valueFields.append("#'{'list[{0}]." + fields[i].getName() + "}");
                    if(i < fields.length - 1){//非最后一个
                        keyFields.append(",");
                        valueFields.append(",");
                    }
                }
            }

            sb.append("INSERT INTO sentinel_metric (" +
                    keyFields.toString() +
                    ") VALUES ");
            MessageFormat mf = new MessageFormat(
                    "(" +
                            valueFields.toString() +
                            ")"
            );
            for (int i = 0; i < list.size(); i++) {
                sb.append(mf.format(new Object[] {i}));
                if (i < list.size() - 1)
                    sb.append(",");
            }
            return sb.toString();
        }
        //查询1
        public String queryList(Map map){
            String app = (String) map.get("app");
            String resource = (String) map.get("resource");
            long startTime = (long) map.get("startTime");
            long endTime = (long) map.get("endTime");

            StringBuffer sql = new StringBuffer("select " +
                    "id," +
                    "gmt_create AS gmtCreate," +
                    "gmt_modified AS gmtModified," +
                    "app," +
                    "timestamp," +
                    "resource," +
                    "pass_qps AS passQps," +
                    "success_qps AS successQps," +
                    "block_qps AS blockQps," +
                    "exception_qps AS exceptionQps," +
                    "rt," +
                    "count," +
                    "resource_code AS resourceCode" +
                    " from sentinel_metric where 1=1 ");

            if(!StringUtil.isEmpty(app)){
                sql.append(" AND ").append(" app = '" + app + "' ");
            }
            if(!StringUtil.isEmpty(resource)){
                sql.append(" AND ").append(" resource = '" + resource + "' ");
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Calendar cal = Calendar.getInstance();
            if(endTime > 0){
                cal.setTimeInMillis(endTime);
                sql.append(" AND ").append(" timestamp <= '" +sdf.format(cal.getTime()) + "' ");
            }
            if(startTime > 0){
                cal.setTimeInMillis(startTime);
                sql.append(" AND ").append(" timestamp >= '" + sdf.format(cal.getTime()) + "' ");
            }
            sql.append(" ORDER BY timestamp DESC");
            return sql.toString();
        }

    }
}
